package com.zhike.api.controller.message;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.zhike.common.dto.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.zhike.common.enums.YesNoEnum;
import com.zhike.common.model.Device;
import com.zhike.common.repository.ACKMessage;
import com.zhike.common.repository.ClearMessage;
import com.zhike.common.repository.HistoryMessage;
import com.zhike.common.vo.UserInfo4Cache;
import com.zhike.service.messages.IACKMessageRepository;
import com.zhike.service.messages.IClearMessageRepository;
import com.zhike.service.messages.IHistoryMessageRepository;
import com.zhike.service.messages.IMessagesService;
import com.zhike.service.messages.EsSearchService;
import com.zhike.service.system.ISystemService;
import com.zhike.utils.cache.GroupsMembersCacheProvider;
import com.zhike.utils.cache.UsersInfoCacheProvider;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

@RestController
@RequestMapping("/api/zkim/message")
@Api(tags = "消息模块")
@Slf4j
public class MessageController {

    @Autowired
    private IHistoryMessageRepository historyMessageRepository;

    @Autowired
    private IACKMessageRepository aIackMessageRepository;

    @Autowired
    private IClearMessageRepository clearMessageRepository;

    @Autowired
    private IMessagesService messagesService;

    @Autowired
    private ISystemService systemService;

    @Autowired
    private UsersInfoCacheProvider usersInfoCacheProvider;

    @Autowired
    private GroupsMembersCacheProvider groupsMembersCacheProvider;

    @Autowired
    private EsSearchService searchService;

    @ApiOperation(value = "查询历史聊天消息", notes = "查询聊天记录的接口")
    @PostMapping("queryMessagePage")
    public R<List<HistoryMessage>> queryMessage(@Validated @RequestBody MessagePageDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();

        List<HistoryMessage> hmList = historyMessageRepository.findHistoryMessagePage(uc.getFakeUid(), dto);

        ConcurrentHashMap<String, GroupMember4Cache> members = null;
        Map<String, ACKMessage> ackMap = null;
        if (hmList.size() > 0) {
            HistoryMessage hm = hmList.get(0);
            if (StringUtils.isNotBlank(hm.getGroupId())) {
                members = groupsMembersCacheProvider.get(hm.getGroupId());
            } else {
                // 查询未回执的消息
                List<ACKMessage> ackList = aIackMessageRepository.findAckMessage(uc.getFakeUid(), hm.getReceiver());
                if (ackList.size() > 0) {
                    ackMap = ackList.stream().collect(Collectors.toMap(ACKMessage::getId, Function.identity()));
                }

            }
        }

        for (HistoryMessage hm : hmList) {
            if (StringUtils.isNotBlank(hm.getGroupId())) { // 群消息
                if (StringUtils.isBlank(hm.getSenderUid())) {
                    continue;
                }
                GroupMember4Cache gmc = members.get(hm.getSenderUid());
                if (gmc == null) {
                    continue;
                }
                if (StringUtils.isNotBlank(gmc.getNicknameIngroup())) {
                    hm.setSenderNickname(gmc.getNicknameIngroup());
                } else {
                    UserInfo4Cache suc = usersInfoCacheProvider.get(hm.getSenderUid());
                    if (suc != null) {
                        hm.setSenderNickname(suc.getNickName());
                    }
                }

            } else { // 单聊
                if (StringUtils.isBlank(hm.getSenderUid())) {
                    continue;
                }
                UserInfo4Cache suc = usersInfoCacheProvider.get(hm.getSenderUid());
                if (suc != null) {
                    hm.setSenderNickname(suc.getNickName());
                }
                hm.setReadStatus(YesNoEnum.YES.getValue());

                if (null != ackMap && null != ackMap.get(hm.getId())) {
                    hm.setReadStatus(YesNoEnum.NO.getValue());
                }
            }
        }

        return R.success(hmList);
    }

    @ApiOperation(value = "删除一条消息")
    @PostMapping("deleteMessage")
    public R<Boolean> deleteMessage(@Validated @RequestBody DelMessageDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();

        List<ClearMessage> cms = new ArrayList<>();
        for (String fp : dto.getFps()) {
            ClearMessage cm = new ClearMessage();
            cm.setFp(fp);
            cm.setSessionId(dto.getSessionId());
            cm.setUserId(uc.getFakeUid());
            cm.setStatus(1);
            cm.setTimestamp(new Date());
            cms.add(cm);
        }

        return R.success(clearMessageRepository.batchSaveClearMessage(cms).size() > 0);
    }

    @ApiOperation(value = "清空消息")
    @PostMapping("clearAll")
    public R<Boolean> clearMessage(@Validated @RequestBody ClearMessageDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        ClearMessage entity = clearMessageRepository.findAndModifyClearRecord(dto.getSessionId(), uc.getFakeUid());
        if (null == entity) {
            ClearMessage cm = new ClearMessage();
            cm.setSessionId(dto.getSessionId());
            cm.setUserId(uc.getFakeUid());
            cm.setTimestamp(new Date());
            cm.setStatus(0);
            clearMessageRepository.saveClearMessage(cm);
        }
        return R.success();
    }

    @ApiOperation(value = "撤回消息", notes = "允许撤回2分钟内的消息")
    @PostMapping("revokeMessage")
    public R<Boolean> revokeMessage(@RequestBody RevokedDTO dto) {
        UserInfo4Cache uc = systemService.getUserInfo();
        return R.success(messagesService.revokeMessage(uc.getFakeUid(), dto));
    }

    @ApiOperation(value = "全文检索")
    @PostMapping("search")
    public RestResp<SearchPageRespDTO<MessageRespDTO>> searchMessage(@RequestBody MessageSearchReqDTO condition) {
        UserInfo4Cache uc = systemService.getUserInfo();
        condition.setSenderUid(uc.getFakeUid());
        return searchService.searchMessage(condition);
    }

    // @ApiIgnore
    @ApiOperation(value = "给用户发消息")
    @PostMapping("sendMessage")
    public R<Boolean> sendMessage(@RequestBody CMDBody4MsgDTO dto) throws Exception {
        UserInfo4Cache uc = systemService.getUserInfo(dto.getToUid());
        String fp = IdUtil.fastSimpleUUID();
        for (Device d : uc.getDeviceList()) {
            messagesService.sendMessageToClient(d.getDeviceNo(), fp, dto.getDataJson());
        }
        return R.success(true);
    }

    // @ApiIgnore
    @ApiOperation(value = "给群组发消息")
    @PostMapping("sendGroupMessage")
    public R<Boolean> sendGroupMessage(@RequestBody CMDBody4MsgDTO dto) throws Exception {
        for (int i = 0; i < 100; i++) {
            String fp = IdUtil.fastSimpleUUID();
            MsgBodyRoot dataJson = dto.getDataJson();
            dataJson.setM(String.valueOf(i));
            messagesService.sendMessageToGroup(fp, JSONUtil.toJsonStr(dto.getDataJson()));
        }
        return R.success(true);
    }

}
